home *** CD-ROM | disk | FTP | other *** search
- /*
- Miranda Installer - Installs nightlies and Miranda addons.
- Copyright (C) 2002-2003 Goblineye Entertainment
-
- Authors: Saar (Tornado) and Kai (kai_b)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- #include "XMLParse.h"
- #pragma hdrstop
-
-
-
- bool XMLParser_FeedDocument(XMLParse_Handler NotifyFunc,char *lpszDoc,LPARAM lParam)
- {
- char *szElementName = NULL; // name of an element (including the fancy stuff. i.e.: "</rdf:RDF>")
- if (NotifyFunc == NULL)
- {
- return(false);
- }
-
- // ok let's get started
- lpszDoc = strchr(lpszDoc,'<');
- // ok now we're at the beginning of the document (we skipped the XML version and encoding element)
- while ((lpszDoc != NULL) && (*lpszDoc != '\0'))
- {
- // at this point lpszDoc always points at the beginning of a new element ('<asd>asd</asd>')
- lpszDoc++; // skip the '<'
-
- // let's check for a comment
- // special handling for comments
- if (strncmp(lpszDoc,"!--",3) == 0) // this is a comment, let's skip it
- {
- char *lpEndComment = strstr(lpszDoc+3,"-->");
-
- if (lpEndComment == NULL) // damn
- {
- return(false);
- }
-
- lpszDoc = strchr(lpEndComment+3,'<'); // start after the next element
- continue;
- }
- else if (*lpszDoc == '!') // DTD, ignore
- {
- // we need to skip it
- lpszDoc = strchr(lpszDoc+1,'<'); // start after the next element
- continue;
- }
- else if (strncmp(lpszDoc,"?xml",4) == 0) // part of the prolog
- {
- // we need to skip it
- char *lpEndDeclare = strstr(lpszDoc+5,"?>");
-
- if (lpEndDeclare == NULL) // damn
- {
- return(false);
- }
-
- lpszDoc = strchr(lpEndDeclare+2,'<'); // start after the next element
- continue;
- }
-
- if (*lpszDoc == '/') // end of element!
- {
- lpszDoc++;
- // notify: end element. data: lpszDoc. len: strchr(lpszDoc,'>') - lpszDoc
- NotifyFunc(XMLPARSER_NOTIFY_ENDELEMENT,lpszDoc,strchr(lpszDoc,'>') - lpszDoc,lParam);
- lpszDoc = strchr(lpszDoc,'<');
- continue;
- }
-
- bool fTagIsEmpty = false;
- char *lpszEndStart = strchr(lpszDoc,'>'); // this is the end of the starting element
-
- if (*(lpszEndStart-1) == '/') // empty tag
- {
- // empty tags are handled pretty much normally, only we don't do any data checks or anything like that
- fTagIsEmpty = true;
- lpszEndStart--; // go back, it will be the end of the tag for now
- }
-
- char *lpszEndNameElement = lpszEndStart; // this is in case of no parameters
- for (char *index=lpszDoc;index < lpszEndStart;index++)
- {
- if ((*index == ' ') || (*index == '\t')) // tag ended
- {
- lpszEndNameElement = index; // btw the end name element is always + 1 from the end of the name
- break;
- }
- }
-
- unsigned int uiLen = lpszEndNameElement - lpszDoc;
-
- if (!fTagIsEmpty) // we only need this if the tag is not empty
- {
- szElementName = new char[uiLen + 4]; // + 1 + 3 (3 - </ >)
-
- if (szElementName == NULL)
- {
- return(false); // error
- }
-
- lstrcpy(szElementName,"</");
- strncat(szElementName,lpszDoc,uiLen);
- szElementName[uiLen + 2] = '>';
- szElementName[uiLen + 3] = '\0';
- }
-
-
- // ok now we notify mother base we found this crap
- // notify: start element. data: lpszDoc. length: lpszEndNameElement - lpszDoc
- NotifyFunc(XMLPARSER_NOTIFY_STARTELEMENT,lpszDoc,lpszEndNameElement - lpszDoc,lParam);
-
- if (lpszEndStart > lpszEndNameElement) // it means we had parameters somewhere in the middle
- {
- // we advance the pointer (skipping the spaces until the start of the arguments)
- while ((*lpszEndNameElement == ' ') || (*lpszEndNameElement == '\t')) lpszEndNameElement++;
- // notify: arguments. data: lpszEndNameElement. length: lpszEndStart - lpszEndNameElement
- NotifyFunc(XMLPARSER_NOTIFY_ARGUMENTS,lpszEndNameElement,lpszEndStart - lpszEndNameElement,lParam);
- }
-
- // ok now handle the end of the element + data
- lpszDoc = ++lpszEndStart;
-
- if (fTagIsEmpty) // we move on
- {
- lpszDoc++; // one more
- lpszDoc = strchr(lpszDoc,'<');
- continue;
- }
-
- char *lpEndOfElement = strstr(lpszDoc,szElementName); // we try to find the end of it
-
- if (lpEndOfElement == NULL) // can't be
- {
- delete [] szElementName;
- return(false);
- }
-
- for (index=lpszDoc;index < lpEndOfElement;index++)
- {
- if (*index == '<') // ok this is, well, not bad, but it means we don't have raw data
- {
- break;
- }
- }
-
- delete [] szElementName;
- szElementName = NULL;
-
- if (index == lpEndOfElement) // came to the end, we have raw data with no elements inside!
- {
- // notify: data. data: lpszDoc; len: lpEndOfElement - lpszDoc
- // if lpEndOfElement == lpszDoc then no data
- NotifyFunc(XMLPARSER_NOTIFY_DATA,lpszDoc,lpEndOfElement - lpszDoc,lParam);
- }
- lpszDoc = strchr(lpszEndStart,'<'); // we start all over again
- }
-
- return(true);
- }